﻿using System;

using System.Collections.Generic;

namespace luozhuang.Commons
{
    public class JavaArrayUtils
    {

        /**
         * An empty immutable {@code Object} array.
         */
        public static Object[] EMPTY_OBJECT_ARRAY = new Object[0];
        /**
         * An empty immutable {@code Class} array.
         */

        /**
         * An empty immutable {@code String} array.
         */
        public static String[] EMPTY_STRING_ARRAY = new String[0];
        /**
         * An empty immutable {@code long} array.
         */
        public static long[] EMPTY_LONG_ARRAY = new long[0];
        /**
         * An empty immutable {@code long} array.
         */
        public static long[] EMPTY_LONG_OBJECT_ARRAY = new long[0];
        /**
         * An empty immutable {@code int} array.
         */
        public static int[] EMPTY_INT_ARRAY = new int[0];
        /**
         * An empty immutable {@code int} array.
         */
        public static int[] EMPTY_INTEGER_OBJECT_ARRAY = new int[0];
        /**
         * An empty immutable {@code short} array.
         */
        public static short[] EMPTY_SHORT_ARRAY = new short[0];
        /**
         * An empty immutable {@code short} array.
         */
        public static short[] EMPTY_SHORT_OBJECT_ARRAY = new short[0];
        /**
         * An empty immutable {@code byte} array.
         */
        public static byte[] EMPTY_BYTE_ARRAY = new byte[0];
        /**
         * An empty immutable {@code Byte} array.
         */
        public static Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
        /**
         * An empty immutable {@code double} array.
         */
        public static double[] EMPTY_DOUBLE_ARRAY = new double[0];
        /**
         * An empty immutable {@code Double} array.
         */
        public static Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
        /**
         * An empty immutable {@code float} array.
         */
        public static float[] EMPTY_FLOAT_ARRAY = new float[0];
        /**
         * An empty immutable {@code float} array.
         */
        public static float[] EMPTY_FLOAT_OBJECT_ARRAY = new float[0];
        /**
         * An empty immutable {@code Boolean} array.
         */
        public static Boolean[] EMPTY_Boolean_ARRAY = new Boolean[0];
        /**
         * An empty immutable {@code Boolean} array.
         */
        public static Boolean[] EMPTY_Boolean_OBJECT_ARRAY = new Boolean[0];
        /**
         * An empty immutable {@code char} array.
         */
        public static char[] EMPTY_CHAR_ARRAY = new char[0];
        /**
         * An empty immutable {@code char} array.
         */
        public static char[] EMPTY_CHARACTER_OBJECT_ARRAY = new char[0];

        /**
         * The index value when an element is not found in a list or array: {@code -1}.
         * This value is returned by methods in this class and can also be used in comparisons with values returned by
         * various method from {@link java.util.List}.
         */
        public static int INDEX_NOT_FOUND = -1;

        /**
         * <p>ArrayUtils instances should NOT be ructed in standard programming.
         * Instead, the class should be used as <code>ArrayUtils.clone(new int[] {2})</code>.</p>
         *
         * <p>This ructor is public to permit tools that require a JavaBean instance
         * to operate.</p>
         */
        public JavaArrayUtils()
        {

        }





        /**
         * <p>Clones an array returning a typecast result and handling
         * {@code null}.</p>
         *
         * <p>This method returns {@code null} for a {@code null} input array.</p>
         *
         * @param array  the array to clone, may be {@code null}
         * @return the cloned array, {@code null} if {@code null} input
         */
        public static long[] clone(long[] array)
        {
            if (array == null)
            {
                return null;
            }
            return (long[])array.Clone();
        }

        // nullToEmpty
        //-----------------------------------------------------------------------
        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static Object[] nullToEmpty(Object[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_OBJECT_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static String[] nullToEmpty(String[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_STRING_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static long[] nullToEmpty(long[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_LONG_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static int[] nullToEmpty(int[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_INT_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static short[] nullToEmpty(short[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_SHORT_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static char[] nullToEmpty(char[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_CHAR_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static byte[] nullToEmpty(byte[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_BYTE_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static double[] nullToEmpty(double[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_DOUBLE_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static float[] nullToEmpty(float[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_FLOAT_ARRAY;
            }
            return array;
        }

        /**
         * <p>Defensive programming technique to change a {@code null}
         * reference to an empty one.</p>
         *
         * <p>This method returns an empty array for a {@code null} input array.</p>
         *
         * <p>As a memory optimizing technique an empty array passed in will be overridden with
         * the empty {@code public static} references in this class.</p>
         *
         * @param array  the array to check for {@code null} or empty
         * @return the same array, {@code public static} empty array if {@code null} or empty input
         * @since 2.5
         */
        public static Boolean[] nullToEmpty(Boolean[] array)
        {
            if (array == null || array.Length == 0)
            {
                return EMPTY_Boolean_ARRAY;
            }
            return array;
        }




        /**
         * <p>Produces a new {@code long} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static long[] subarray(long[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_LONG_ARRAY;
            }

            long[] subarray = new long[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code int} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static int[] subarray(int[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_INT_ARRAY;
            }

            int[] subarray = new int[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code short} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static short[] subarray(short[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_SHORT_ARRAY;
            }

            short[] subarray = new short[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code char} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static char[] subarray(char[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_CHAR_ARRAY;
            }

            char[] subarray = new char[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code byte} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static byte[] subarray(byte[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_BYTE_ARRAY;
            }

            byte[] subarray = new byte[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code double} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static double[] subarray(double[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_DOUBLE_ARRAY;
            }

            double[] subarray = new double[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code float} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static float[] subarray(float[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_FLOAT_ARRAY;
            }

            float[] subarray = new float[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        /**
         * <p>Produces a new {@code Boolean} array containing the elements
         * between the start and end indices.</p>
         *
         * <p>The start index is inclusive, the end index exclusive.
         * Null array input produces null output.</p>
         *
         * @param array  the array
         * @param startIndexInclusive  the starting index. Undervalue (&lt;0)
         *      is promoted to 0, overvalue (&gt;array.Length) results
         *      in an empty array.
         * @param endIndexExclusive  elements up to endIndex-1 are present in the
         *      returned subarray. Undervalue (&lt; startIndex) produces
         *      empty array, overvalue (&gt;array.Length) is demoted to
         *      array Length.
         * @return a new array containing the elements between
         *      the start and end indices.
         * @since 2.1
         */
        public static Boolean[] subarray(Boolean[] array, int startIndexInclusive, int endIndexExclusive)
        {
            if (array == null)
            {
                return null;
            }
            if (startIndexInclusive < 0)
            {
                startIndexInclusive = 0;
            }
            if (endIndexExclusive > array.Length)
            {
                endIndexExclusive = array.Length;
            }
            int newSize = endIndexExclusive - startIndexInclusive;
            if (newSize <= 0)
            {
                return EMPTY_Boolean_ARRAY;
            }

            Boolean[] subarray = new Boolean[newSize];
            System.Array.Copy(array, startIndexInclusive, subarray, 0, newSize);
            return subarray;
        }

        // Is same Length
        //-----------------------------------------------------------------------
        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.
         *
         * <p>Any multi-dimensional aspects of the arrays are ignored.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(Object[] array1, Object[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(long[] array1, long[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(int[] array1, int[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(short[] array1, short[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(char[] array1, char[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(byte[] array1, byte[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(double[] array1, double[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(float[] array1, float[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }

        /**
         * <p>Checks whether two arrays are the same Length, treating
         * {@code null} arrays as Length {@code 0}.</p>
         *
         * @param array1 the first array, may be {@code null}
         * @param array2 the second array, may be {@code null}
         * @return {@code true} if Length of arrays matches, treating
         *  {@code null} as an empty array
         */
        public static Boolean isSameLength(Boolean[] array1, Boolean[] array2)
        {
            if ((array1 == null && array2 != null && array2.Length > 0) ||
                (array2 == null && array1 != null && array1.Length > 0) ||
                (array1 != null && array2 != null && array1.Length != array2.Length))
            {
                return false;
            }
            return true;
        }



        /*

        // Reverse
        //-----------------------------------------------------------------------
        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>There is no special handling for multi-dimensional arrays.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(Object[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            Object tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(long[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            long tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(int[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            int tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(short[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            short tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(char[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            char tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(byte[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            byte tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(double[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            double tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(float[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            float tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }

        /**
         * <p>Reverses the order of the given array.</p>
         *
         * <p>This method does nothing for a {@code null} input array.</p>
         *
         * @param array  the array to reverse, may be {@code null}
         */
        public static void reverse(Boolean[] array)
        {
            if (array == null)
            {
                return;
            }
            int i = 0;
            int j = array.Length - 1;
            Boolean tmp;
            while (j > i)
            {
                tmp = array[j];
                array[j] = array[i];
                array[i] = tmp;
                j--;
                i++;
            }
        }



        // ----------------------------------------------------------------------
        /**
         * <p>Checks if an array of Objects is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(Object[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive longs is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(long[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive ints is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(int[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive shorts is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(short[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive chars is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(char[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive bytes is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(byte[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive doubles is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(double[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive floats is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(float[] array)
        {
            return array == null || array.Length == 0;
        }

        /**
         * <p>Checks if an array of primitive Booleans is empty or {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is empty or {@code null}
         * @since 2.1
         */
        public static Boolean isEmpty(Boolean[] array)
        {
            return array == null || array.Length == 0;
        }



        /**
         * <p>Checks if an array of primitive longs is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(long[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive ints is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(int[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive shorts is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(short[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive chars is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(char[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive bytes is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(byte[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive doubles is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(double[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive floats is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(float[] array)
        {
            return (array != null && array.Length != 0);
        }

        /**
         * <p>Checks if an array of primitive Booleans is not empty or not {@code null}.</p>
         *
         * @param array  the array to test
         * @return {@code true} if the array is not empty or not {@code null}
         * @since 2.5
         */
        public static Boolean isNotEmpty(Boolean[] array)
        {
            return (array != null && array.Length != 0);
        }

        // Filling

        /**
         * Assigns the specified long value to each element of the specified array
         * of longs.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(long[] a, long val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified long value to each element of the specified
         * range of the specified array of longs.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(long[] a, int fromIndex, int toIndex, long val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified int value to each element of the specified array
         * of ints.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(int[] a, int val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified int value to each element of the specified
         * range of the specified array of ints.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(int[] a, int fromIndex, int toIndex, int val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified short value to each element of the specified array
         * of shorts.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(short[] a, short val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified short value to each element of the specified
         * range of the specified array of shorts.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(short[] a, int fromIndex, int toIndex, short val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified char value to each element of the specified array
         * of chars.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(char[] a, char val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified char value to each element of the specified
         * range of the specified array of chars.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(char[] a, int fromIndex, int toIndex, char val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified byte value to each element of the specified array
         * of bytes.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(byte[] a, byte val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified byte value to each element of the specified
         * range of the specified array of bytes.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(byte[] a, int fromIndex, int toIndex, byte val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified Boolean value to each element of the specified
         * array of Booleans.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(Boolean[] a, Boolean val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified Boolean value to each element of the specified
         * range of the specified array of Booleans.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(Boolean[] a, int fromIndex, int toIndex,
                                Boolean val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified double value to each element of the specified
         * array of doubles.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(double[] a, double val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified double value to each element of the specified
         * range of the specified array of doubles.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(double[] a, int fromIndex, int toIndex, double val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified float value to each element of the specified array
         * of floats.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         */
        public static void fill(float[] a, float val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified float value to each element of the specified
         * range of the specified array of floats.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         */
        public static void fill(float[] a, int fromIndex, int toIndex, float val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified Object reference to each element of the specified
         * array of Objects.
         *
         * @param a the array to be filled
         * @param val the value to be stored in all elements of the array
         * @throws ArrayStoreException if the specified value is not of a
         *         runtime type that can be stored in the specified array
         */
        public static void fill(Object[] a, Object val)
        {
            for (int i = 0, len = a.Length; i < len; i++)
                a[i] = val;
        }

        /**
         * Assigns the specified Object reference to each element of the specified
         * range of the specified array of Objects.  The range to be filled
         * extends from index <tt>fromIndex</tt>, inclusive, to index
         * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
         * range to be filled is empty.)
         *
         * @param a the array to be filled
         * @param fromIndex the index of the first element (inclusive) to be
         *        filled with the specified value
         * @param toIndex the index of the last element (exclusive) to be
         *        filled with the specified value
         * @param val the value to be stored in all elements of the array
         * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
         * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
         *         <tt>toIndex &gt; a.Length</tt>
         * @throws ArrayStoreException if the specified value is not of a
         *         runtime type that can be stored in the specified array
         */
        public static void fill(Object[] a, int fromIndex, int toIndex, Object val)
        {
            rangeCheck(a.Length, fromIndex, toIndex);
            for (int i = fromIndex; i < toIndex; i++)
                a[i] = val;
        }

        /**
   * Checks that {@code fromIndex} and {@code toIndex} are in
   * the range and throws an appropriate exception, if they aren't.
   */
        private static void rangeCheck(int Length, int fromIndex, int toIndex)
        {
            if (fromIndex > toIndex)
            {
                throw new Exception(
                    "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
            }
            if (fromIndex < 0)
            {
                throw new IndexOutOfRangeException(fromIndex.ToString());
            }
            if (toIndex > Length)
            {
                throw new IndexOutOfRangeException(toIndex.ToString());
            }
        }

    }

}
